#include "stdafx.h"
#include "HeightMap.h"

#include <stdlib.h>

namespace MyGame {

HeightMap::HeightMap(UINT width, UINT length) {
    this->length = length;
    this->width = width;
    this->map = new FLOAT*[this->width];
    for (UINT h = 0; h < this->width; ++h) {
        this->map[h] = new FLOAT[length];
        for (UINT w = 0; w < this->length; ++w) {
            this->map[h][w] = 0.0f;
        }
    }
}

HeightMap::~HeightMap(void) {
    for (UINT w = 0; w < this->width; ++w) {
        delete [] this->map[w];
    }

    delete [] this->map;
}

int HeightMap::GetLength() {
    return this->length;
}

FLOAT** HeightMap::GetMap() {
    return this->map;
}

FLOAT HeightMap::GetMaxElevation() {
    FLOAT maxElevation = 0;
    for (UINT h = 0; h < this->width; ++h) {
        for (UINT w = 0; w < this->length; ++w) {
            if (this->map[h][w] > maxElevation) {
                maxElevation = this->map[h][w];
            }
        }
    }

    return maxElevation;
}

int HeightMap::GetWidth() {
    return this->width;
}

void HeightMap::Blend(HeightMap* h1, HeightMap* h2, FLOAT amount) {
    if (h1->GetWidth() != h2->GetWidth() || h1->GetLength() != h2->GetLength()) {
        return;
    }

    int width = h1->GetWidth();
    int length = h2->GetLength();
    FLOAT** map1 = h1->GetMap();
    FLOAT** map2 = h2->GetMap();
    FLOAT amount2 = 1.0f - amount;
    for (int w = 0; w < width; ++w) {
        for (int l = 0; l < length; ++l) {
            map1[w][l] = amount * map1[w][l] + amount2 * map2[w][l];
        }
    }
}

HeightMap* HeightMap::Clone() {
    HeightMap* heightMap = new HeightMap(this->width, this->length);
    FLOAT** newMap = heightMap->GetMap();
    for (UINT w = 0; w < this->width; ++w) {
        for (UINT l = 0; l < this->length; ++l) {
            newMap[w][l] = this->map[w][l];
        }
    }

    return heightMap;
}

HeightMap* HeightMap::Crop(HeightMap* heightMap, int w1, int l1, int w2, int l2) {
    if (w2 >= heightMap->GetWidth()) {
        w2 = heightMap->GetWidth() - 1;
    }

    if (l2 >= heightMap->GetLength()) {
        l2 = heightMap->GetLength() - 1;
    }

    int width = w2 - w1 + 1;
    int length = l2 - l1 + 1;
    HeightMap* newHeightMap = new HeightMap(width, length);

    FLOAT** newMap = newHeightMap->GetMap();
    FLOAT** map = heightMap->GetMap();
    for (int w = 0; w < width; ++w) {
        for (int l = 0; l < length; ++l) {
            newMap[w][l] = map[w + w1][l + l1];
        }
    }

    return newHeightMap;
}

void HeightMap::Normalize(HeightMap* heightMap) {
    HeightMap::Normalize(heightMap, 1);
}

void HeightMap::Normalize(HeightMap* heightMap, FLOAT scale) {
    FLOAT min = 1000.0f;
    FLOAT max = 0.0f;
    FLOAT** map = heightMap->GetMap();
    int length = heightMap->GetLength();
    int width = heightMap->GetWidth();
    for (int w = 0; w < width; ++w) {
        for (int l = 0; l < length; ++l) {
            if (map[w][l] < min) {
                min = map[w][l];
            }
            if (map[w][l] > max) {
                max = map[w][l];
            }
        }
    }

    FLOAT delta = (max - min) / scale;
    if (delta == 0) {
        return;
    }

    for (int w = 0; w < width; ++w) {
        for (int l = 0; l < length; ++l) {
            map[w][l] = (map[w][l] - min) / delta;
        }
    }
}

}